package rhinestone.Control;

import java.util.Iterator;
import javax.naming.LimitExceededException;
import javax.naming.NameNotFoundException;
import rhinestone.TUI.MainMenuUI;
import rhinestone.Model.Sale;
import rhinestone.Model.SaleContainer;
import rhinestone.Model.Item;
import rhinestone.Model.Product;
import rhinestone.Model.ProductContainer;
import rhinestone.Model.Pack;
import rhinestone.Model.PackContainer;
import rhinestone.Model.Customer;
import rhinestone.Model.CustomerContainer;
import rhinestone.Vlad_GUI.NewJFrame;

/**
 * The class is responsible for controlling the checkouts.
 *
 * @author Group 2
 * @version 2010.12.12
 */
public final class SaleController {
	private ProductContainer productContainer;
	private PackContainer packContainer;
	private CustomerContainer customerContainer;
	private SaleContainer saleContainer;
	private Sale sale;
	
	/**
	 * Constructor
	 */
	public SaleController(ProductContainer productContainer, CustomerContainer customerContainer, PackContainer packContainer, SaleContainer saleContainer) {
		this.productContainer = productContainer;
		this.customerContainer = customerContainer;
		this.packContainer = packContainer;
		this.saleContainer = saleContainer;
		initializeSale();
	}

	public void initializeSale() {
		sale = new Sale(NewJFrame.LOGGED_IN);
	}

	public Sale getCurrentSale() {
		return sale;
	}

	/**
	 * Called by UI when the product is scanned.
	 * @param barcode The bar code of the scanned product.
	 */
	public Item addItem(String barcode, int amount) throws LimitExceededException, NameNotFoundException {
		Product product = productContainer.getProduct(barcode);
		if(product != null) {
			int availableAmount = product.getAmountInDIY() + product.getAmountInTimberyard();
			if(availableAmount >= amount) {
				sale.addProduct(product, amount);
				return (Item) product;
			}
			else {
				//System.out.println("Cannot add " + amount + " products. Available in stock: " + availableAmount);
				throw new LimitExceededException();
			}
		}

		Pack pack = packContainer.getPack(barcode);
		if(pack != null) {
			int availableAmount = pack.getAvailablAmount();
			if(availableAmount >= amount) {
				sale.addPack(pack, amount);
				return (Item) pack;
			}
			else
				System.err.println("Cannot add " + amount + " packs. Available in stock: " + availableAmount);
		}
		else {
			//System.out.println("Item with bar code " + barcode + " does not exists.");
			throw new NameNotFoundException();
		}
		return null;
	}

	/**
	 * Called by UI when the scanning of products is done to finish the sale.
	 * @param customerCpr The customers cpr is passed. If not null, checks if the person is registered as customer and checks for available discounts.
	 */
	public Sale checkoutItems(String customerCpr) {
		if(sale.getItemCount() > 0) {
			sale.updateItemContainers();
			if(!customerCpr.equals("")) {
				Customer customer = customerContainer.getCustomer(customerCpr);
				sale.addCustomer(customer);
			}
			saleContainer.addSale(sale);
			return sale;
		}
		return null;
	}

	/**
	 * Removes the mistakenly added product from the current sale.
	 * @param barcode The bar code of the product to remove.
	 */
	public Item removeItem(String barcode, int amount) {
		Product product = sale.getProduct(barcode);
		if(product != null) {
			sale.removeProduct(product, amount);
			return (Item) product;
		}
		Pack pack = sale.getPack(barcode);
		if(pack != null) {
			sale.removePack(pack, amount);
			return (Item) pack;
		}
		return null;
	}

	/**
	 * Destroys the current sale with all the scanned products.
	 */
	public void cancelSale() {
		sale = null;
		System.out.println(" --- Sale canceled. ---");
	}

	/**
	 * Don't pay attention to this. In final application version it will be removed.
	 */
	private void pause() {
		try {
			Thread.sleep(1000);
		} catch(InterruptedException ex) {
			ex.printStackTrace();
		}
	}

	public String generateReceipt(Sale sale) {
		String receipt = "";
		receipt += "\n-------------------------------------";
		receipt += "\n------------- RECEIPT ---------------";
		receipt += "\n-------------------------------------";
		Iterator<Product> products = sale.getProducts();
		while(products.hasNext()) {
			Product product = products.next();
			receipt += "\n" + sale.getAmount(product) + "x " + product.getName() + " -- " + (sale.getAmount(product) * product.getPrice());
		}
		Iterator<Pack> packs = sale.getPacks();
		while(packs.hasNext()) {
			Pack pack = packs.next();
			receipt += "\n" + sale.getAmount(pack) + "x " + pack.getName() + " -- " + (sale.getAmount(pack) * pack.getPrice());
		}
		receipt += "\n-------------------------------------";
		receipt += "\nTotal price: $" + sale.getTotalPrice();
		if(sale.hasCustomer()) {
			receipt += "\nApplying customers discount...";
			receipt += "\nTotal price with discount: $" + sale.applyCustomerDiscount(sale.getTotalPrice());
		}
		return receipt;
	}
}
